import {
  Ref,
  Suspense,
  forwardRef,
  lazy,
  useEffect,
  useImperativeHandle,
  useMemo,
  useState,
} from "react";
import "../style/DesignerGlobalStyle.less";
import { observer } from "mobx-react";
import "../resource/font/FontGlobal.css";
import operatorMap from "framework/operate";
import FileUtil from "utils/FileUtil";
import { DesignerProvider } from "components/common/DesignerContext";
import { AxiosInstance } from "axios";
import { Loading } from "tdesign-react";
import DesignerCanvas from "designer/canvas/DesignerCanvas";
import {
  SaveType,
  IProjectInfo,
  DesignerMode,
  CanvasConfig,
} from "designer/DesignerType";
import DesignerLoaderFactory from "designer/loader/DesignerLoaderFactory";
import designerManager from "designer/manager/DesignerManager";
import ScaleAction from "../../framework/core/ScaleAction";
import { IotDeviceData } from "_common/DataType";
import { getControllers } from "framework/utils/LayerUtil";
import layerManager from "designer/manager/LayerManager";
import { ViewerState } from "components";
import filterManager from "designer/manager/FilterManager";
const ScreenFit = lazy(() => import("../../framework/screen-fit/ScreenFit"));
export interface DesignerProps {
  facilityId?: number;
  /**
   * 预览项目
   * @param id 项目id
   * @param type
   * @returns
   */
  onPreview?: (id: string, type: SaveType) => void;

  /**
   * 保存项目
   * @param id 项目id
   * @param json 场景json
   * @returns
   */
  onSave?: (id: string, json: string) => void;
  onExport?: (id: string, json: string) => void;

  /**
   * axios配置
   */
  axios?: AxiosInstance;

  // 产品分类编码,用来过滤组件
  productCodes?: number[];

  onClick?: (deviceCode: string) => void;

  width: number;
  height: number;
}

export interface DesignerInstance {
  /**
   * 创建场景项目
   * @param name 场景名称
   * @param desc 场景描述
   * @returns 项目id
   */
  create: (name: string, facilityId?: string) => Promise<string>;
  /**
   * 加载场景项目
   * @param dataJson 项目json
   * @returns
   */
  load: (dataJson: string) => void;
  // 销毁
  destroy: () => void;

  /**
   * 更新设备数据
   * @param data 设备
   * @returns
   * */
  updateData?: (data: IotDeviceData) => void;

  // 操作画布
  setLayout?: (layout: any) => void;
}

const DesignerViewer = forwardRef(
  (props: DesignerProps, ref: Ref<DesignerInstance>) => {
    const { axios, facilityId, productCodes, onClick, width, height } = props;
    const staticType = SaveType.LOCAL; // 只在本地存储
    const [projectId, setProjectId] = useState<string>();
    const { compController } = layerManager!;
    const [lock, setLock] = useState<boolean>(true);

    //记录canvas 配置数据
    const [canvasConfig, setCanvasConfig] = useState<CanvasConfig>();

    // 记录当前的比例
    const [scale] = useState<number>();
    // 加载项目
    useImperativeHandle(ref, () => ({
      create: (name) => createDesigner(name),
      load: (dataJson) => loadProject(dataJson),
      destroy: () => {
        designerManager.destroy();
      },
      updateData: updateDeviceData,
      setLayout: (_lock) => {
        setLock(_lock);
      },
    }));

    useEffect(() => {
      layerManager.setEnableEvent(true);
      ViewerState.handleClick = (data) => {
        onClick?.(data);
      };
      return () => {
        layerManager.setEnableEvent(false);
        // 销毁
        designerManager.destroy();
        filterManager.destroy();
        layerManager.destroy();
      };
    }, []);

    const updateDeviceData = (data: IotDeviceData) => {
      if (data && data.dtCode) {
        const controllers = getControllers(compController, data.dtCode);
        controllers?.forEach((a) => {
          a.changeData(data);
        });
      }
    };

    // 初始化项目
    const initialization = async (project: IProjectInfo) => {
      const pid = await operatorMap[staticType].createProject(project);
      const _time = setTimeout(() => {
        //加载设计器
        DesignerLoaderFactory.getLoader(DesignerMode.EDIT).load(
          pid,
          staticType
        );
        setProjectId(pid);
        //绑定事件到dom元素
        clearTimeout(_time);
      }, 500);
      return pid;
    };

    /**
     * 创建设计器
     * @param name 场景名称
     * @param desc 场景描述
     * @returns 场景id
     */
    const createDesigner = async (name: string) => {
      const project: IProjectInfo = {
        name,
        des: "",
        saveType: staticType,
        dataJson: JSON.stringify({
          canvasManager: { width: 1920, height: 1080 },
        }),
      };
      return await initialization(project);
    };

    const loadProject = async (dataJson: string) => {
      // 加载数据前先初始化数据
      const importData = JSON.parse(dataJson);

      // 初始化
      const projectData = importData.data;
      setCanvasConfig(projectData.canvasManager);
      const elemConfigs = projectData?.layerManager?.elemConfigs;
      const promises: Promise<void>[] = [];
      if (elemConfigs) {
        Object.keys(elemConfigs).forEach((key) => {
          const item = elemConfigs[key];
          if (
            item.base.type === "BaseImage" &&
            (item.style.localUrl as string)?.startsWith("blob")
          ) {
            // 将 blob 数据转换为 base64，并将异步操作添加到 promises 数组中
            promises.push(
              FileUtil.base64ToBlob(item.style.localUrl as string).then(
                (res: string | boolean) => {
                  if (res) item.style.localUrl = res;
                  else {
                    console.error(
                      `${item.base.id + "_" + item.base.name} 图片blob转换失败, ${item.style.localUrl}`
                    );
                  }
                }
              )
            );
          }
        });
      }
      await Promise.all(promises);
      // console.log("projectData:", projectData);
      //designerManager.init(projectData as any, DesignerMode.EDIT);
      const project: IProjectInfo = {
        name: "",
        des: "",
        id: importData.id,
        saveType: staticType,
        dataJson: JSON.stringify(projectData),
      };
      setProjectId(importData.id);
      await initialization(project);
    };

    const canvasNode = useMemo(() => {
      if (!canvasConfig) return null;

      return (
        <Suspense fallback={<Loading />}>
          <ScreenFit
            width={width}
            height={height!}
            mode={"scale"}
            scaleChange={(xScale, yScale) => {
              ScaleAction.doScale(xScale, yScale);
            }}
          >
            <div
              style={{
                width: canvasConfig.width,
                height: canvasConfig.height,
                overflow: "hidden",
                position: "relative",
                transformOrigin: "left top",
                transform: `scale(${width / (canvasConfig.width ?? 0)},${height / (canvasConfig.height ?? 0)})`,
              }}
            >
              <DesignerCanvas
                view={true}
                scale={scale}
                id={projectId}
                lock={lock}
                height={canvasConfig.height}
                width={canvasConfig.width}
              />
            </div>
          </ScreenFit>
        </Suspense>
      );
    }, [canvasConfig, projectId, lock, width, height]);

    const { loaded } = designerManager;
    if (!loaded) return <Loading />;

    return (
      <DesignerProvider
        axios={axios}
        facilityId={facilityId}
        productCodes={productCodes}
      >
        {/* <div style={{ height: "100%" }}> */}

        {canvasNode}
        {/* <FrameLayout
            content={
             
            }
          /> */}
        {/* </div> */}
      </DesignerProvider>
    );
  }
);

export default observer(DesignerViewer);
